package com.gang.service;

import cn.afterturn.easypoi.word.WordExportUtil;
import cn.hutool.core.date.DateTime;
import com.gang.conf.FiscoBcos;
import com.gang.dao.DatebaseMapper;
import com.gang.feign.UserFeign;
import com.gang.pojo.CommonResult;
import com.gang.pojo.Datas;
import com.gang.pojo.Vp;
import com.gang.utils.DidGetUtil;
import com.gang.utils.SM3;
import com.gang.utils.UserDataUtil;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.fisco.bcos.sdk.BcosSDK;
import org.fisco.bcos.sdk.abi.datatypes.Address;
import org.fisco.bcos.sdk.client.Client;
import org.fisco.bcos.sdk.crypto.CryptoSuite;
import org.fisco.bcos.sdk.crypto.keypair.CryptoKeyPair;
import org.fisco.bcos.sdk.crypto.signature.ECDSASignature;
import org.fisco.bcos.sdk.model.CryptoType;
import org.fisco.bcos.sdk.model.TransactionReceipt;
import org.fisco.bcos.sdk.transaction.manager.AssembleTransactionProcessor;
import org.fisco.bcos.sdk.transaction.manager.TransactionProcessorFactory;
import org.fisco.bcos.sdk.transaction.model.dto.CallResponse;
import org.fisco.bcos.sdk.transaction.model.dto.TransactionResponse;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.io.*;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

@Service
public class BlockServiceImpl implements BlockService{

    @Autowired
    FiscoBcos fiscoBcos;
    @Autowired
    UserFeign userFeign;
    @Autowired
    DatebaseMapper datebaseMapper;
    @Override
    public UUID getPubPriKey() {
        CryptoSuite cryptoSuite = new CryptoSuite(CryptoType.ECDSA_TYPE);
        CryptoKeyPair keyPair = cryptoSuite.createKeyPair();
        String hexPrivateKey = keyPair.getHexPrivateKey();
        String hexPublicKey = keyPair.getHexPublicKey();
        String address = keyPair.getAddress();
        List<String> strings = new ArrayList<>();
        ECDSASignature ecdsaSignature = new ECDSASignature();
        strings.add(hexPrivateKey);
        strings.add(hexPublicKey);
        strings.add(address);
        UUID uuid = UUID.randomUUID();
        File file = new File("H:\\"+ uuid+".txt");

        try {
            BufferedWriter   bw = new BufferedWriter(new FileWriter(file));
            bw.write("公钥:");
            bw.write(strings.get(1));
            bw.write("\n");
            bw.write("私钥:");
            bw.write(strings.get(0));
            bw.write("\n");
            bw.write("地址:");
            bw.write(strings.get(2));
            bw.flush();
            bw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return uuid;
    }

    @Override
    public String getDidAndToChain(String pub,String pri) throws Exception {
        String did = DidGetUtil.getDID();

        Client client = fiscoBcos.getBcosSDK().getClient(Integer.valueOf(1));
        CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(pri);
            ArrayList<Object> list = new ArrayList<>();
            list.add(did);
            list.add(pub);
            AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client,keyPair,"H:\\JavaTest\\sharepark-cloud\\server\\blockchain11000\\src\\main\\resources\\abi","");
            TransactionResponse response = transactionProcessor.sendTransactionAndGetResponseByContractLoader("DID","0x0c708d5075d26dc0ed69a691f757b7162197bdda","addDID",list);
            ArrayList<Object> strings = new ArrayList<>();
            strings.add(did);
            transactionProcessor.sendTransactionAndGetResponseByContractLoader("verification","0x5293c2aff9d56f6c8c4c8d497a9a42d7dd47564b","storedid",strings);
        return did;
    }

    @Override
    public UUID getVC(String did,String pub,String data,String pri) {
        ECDSASignature ecdsaSignature = new ECDSASignature();
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("did", did);
        map.put("pub", pub);
        StringBuilder sb = new StringBuilder();
        StringBuilder sb1 = new StringBuilder();
        while (data.indexOf(',')!=-1){
            String s=data.substring(0,data.indexOf(','));
            sb.append(s);
            sb.append("("+SM3.generateSM3HASH(s)+")  ");
            sb1.append(SM3.generateSM3HASH(s));
            data=data.substring(data.indexOf(',')+1,data.length());
        }
        sb.append(data+"("+SM3.generateSM3HASH(data)+")");
        sb1.append(SM3.generateSM3HASH(data));
        String root = SM3.generateSM3HASH(sb1.toString());
        map.put("identity",sb.toString());
        map.put("root", root);
        Client client = fiscoBcos.getBcosSDK().getClient(Integer.valueOf(1));
        CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(pri);
        map.put("sign", ecdsaSignature.signWithStringSignature(root,keyPair));

        DateTimeFormatter formatter2 = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = formatter2.format(LocalDateTime.now());
        map.put("time", format);
        String s = SM3.generateSM3HASH(format);
        map.put("hash", s);
        UUID uuid=null;
        try {
            XWPFDocument doc = WordExportUtil.exportWord07("H:\\vcmoban.docx", map);
            uuid = UUID.randomUUID();
            FileOutputStream fos = new FileOutputStream("H:/"+uuid+".docx");
            doc.write(fos);
            fos.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return uuid;
    }

    @Override
    public UUID getVP(String did,String pub,String data,String root,String sign, String pri) {
        Map<String, Object> map = new HashMap<String, Object>();
        map.put("pub", pub);
        map.put("identity", data);
        map.put("root", root);
        map.put("sign", sign);
        DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        String format = dateTimeFormatter.format(LocalDateTime.now());
        map.put("time", format);
        UUID uuid = UUID.randomUUID();
        String s3 = SM3.generateSM3HASH(did + format);
        map.put("hash", s3);
        Client client = fiscoBcos.getBcosSDK().getClient(Integer.valueOf(1));
        CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(pri);
        ArrayList<Object> list = new ArrayList<>();
        list.add(did);
        list.add(format);
        list.add(s3);
        try {
            AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "H:\\JavaTest\\sharepark-cloud\\server\\blockchain11000\\src\\main\\resources\\abi", "");
            transactionProcessor.sendTransactionAndGetResponseByContractLoader("verification", "0x5293c2aff9d56f6c8c4c8d497a9a42d7dd47564b", "apply", list);
        } catch (Exception e) {
            e.printStackTrace();
        }
        try {
            XWPFDocument doc = WordExportUtil.exportWord07("H:\\vpmoban.docx", map);
            uuid = UUID.randomUUID();
            FileOutputStream fos = new FileOutputStream("H:/" + uuid + ".docx");
            doc.write(fos);
            fos.close();
        } catch (Exception e) {

        }
        return uuid;
    }

    @Override
    public String  verifyRoot(String data,int index) {

        String userData = UserDataUtil.getUserData(index, data);
        data=data.replaceAll(userData,SM3.generateSM3HASH(userData));
        data=data.replaceAll(",","");
        return SM3.generateSM3HASH(data);

    }

    @Override
    public Boolean verifySign(int index,String data,String sign, String pub) {
        ECDSASignature ecdsaSignature = new ECDSASignature();

        String userData = UserDataUtil.getUserData(index, data);
        String s = SM3.generateSM3HASH(userData);
        data=data.replaceAll(userData,s);

        String s1 = data.replaceAll(",", "");
        String s2 = SM3.generateSM3HASH(s1);
        return ecdsaSignature.verify(pub,s2,sign);
    }

    @Override
    public String verifyDid(String vphash, String time) {
        Vp vp = datebaseMapper.getVp(vphash);
        String username = vp.getUsername();
        CommonResult userDid = userFeign.getUserDid(username);
        return SM3.generateSM3HASH(userDid.getData()+time);
    }

    @Override
    public String getDid(String pri,String vphash) {
        Client client = fiscoBcos.getBcosSDK().getClient(Integer.valueOf(1));
        CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(pri);
        AssembleTransactionProcessor transactionProcessor = null;
        ArrayList<Object> strings = new ArrayList<>();
        strings.add(vphash);
        String result="";
        try {
            transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "H:\\JavaTest\\sharepark-cloud\\server\\blockchain11000\\src\\main\\resources\\abi", "");

            CallResponse callResponse = transactionProcessor.sendCallByContractLoader("verification", "0x5293c2aff9d56f6c8c4c8d497a9a42d7dd47564b", "getDID", strings);
            result= callResponse.getValues();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return result;
    }

    @Override
    public String deployContract(String pri) {
        Client client = fiscoBcos.getBcosSDK().getClient(Integer.valueOf(1));
        CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(pri);
        try {
            AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "H:\\JavaTest\\sharepark-cloud\\server\\blockchain11000\\src\\main\\resources\\abi", "H:\\JavaTest\\sharepark-cloud\\server\\blockchain11000\\src\\main\\resources\\bin");
            TransactionResponse verification = transactionProcessor.deployByContractLoader("verification", new ArrayList<>());
            return verification.getContractAddress();
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "";
    }

    @Override
    public Datas setnft(String tokenURI, String pri, String addr) {
        Client client = fiscoBcos.getBcosSDK().getClient(Integer.valueOf(1));
        CryptoKeyPair keyPair = client.getCryptoSuite().createKeyPair(pri);
        ArrayList<Object> objects = new ArrayList<>();
        Datas datas = new Datas();
        try {
            objects.add(addr);
            objects.add(tokenURI);
            AssembleTransactionProcessor transactionProcessor = TransactionProcessorFactory.createAssembleTransactionProcessor(client, keyPair, "H:\\JavaTest\\sharepark-cloud\\server\\blockchain11000\\src\\main\\resources\\abi", "");
            TransactionResponse response = transactionProcessor.sendTransactionAndGetResponse("NFT", "0x377522832de531237f51ef0c4fd79f2b01cc171f", "mint", objects);
            datas.setTokenURI(tokenURI);
            datas.setBlocknumber(Integer.valueOf(response.getTransactionReceipt().getBlockNumber(),16));
            datas.setCaddr(response.getContractAddress());
            datas.setOaddr(addr);
            datas.setTokenid(Integer.valueOf(response.getValues()));
            datas.setTxhash(response.getTransactionReceipt().getTransactionHash());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return datas;
    }
}
